import pyautogui
import time
import json
import os
import keyboard
import sys

# --------------------- 操作指南 ---------------------
def print_usage_guide():
    """打印操作指南"""
    guide = """
    操作指南:
    1. 启动程序后，vscode将处于最小化状态。
    2. 确保已进入任务章节界面，程序会自动识别并点击相应的按钮。
    3. 按 ESC 键可以随时停止程序。
    
    温馨提示：
    1. 本程序在小概率情况下会识别不出对应的图像，建议每隔2小时查看一次刷课情况
    2. 如果程序无法正常运行，请前往 auto_learn_config.json 检查配置文件是否正确，或手动调整图像识别的置信度。
    3. 在最小化vscode代码处，如何根据机子修改坐标鼠标位置？详见实验报告~
    """
    print(guide)

# --------------------- 配置管理 ---------------------
def load_config():
    """加载配置文件，如果不存在则创建默认配置"""
    config_path = "auto_learn_config.json"
    
    # 默认配置
    default_config = {
        "image_dir": "D:/Administrator/Documents/zzhFile/Study/Python/last/auto/cmp/",
        "sleep_time": 0.6,
        "multi_choice_sequences": [
            ["A", "B", "C", "D"],
            ["A", "B", "C"],
            ["A", "B"],
            ["A", "C"],
            ["A", "D"],
            ["B", "C", "D"],
            ["B", "C"],
            ["B", "D"],
            ["C", "D"]
        ],
        "confidence": 0.75,
        "scroll_amount": -100,
        "max_scroll_attempts": 2,
        "scroll_wait_time": 1,
        "next_page_wait": 2
    }
    
    try:
        # 如果配置文件存在则加载
        if os.path.exists(config_path):
            with open(config_path, 'r') as f:
                config = json.load(f)
                print("配置加载成功")
                return config
    except Exception as e:
        print(f"加载配置失败: {e}")
    
    # 创建默认配置文件
    try:
        with open(config_path, 'w') as f:
            json.dump(default_config, f, indent=4)
        print("创建默认配置文件")
        return default_config
    except Exception as e:
        print(f"创建配置文件失败: {e}")
        return default_config

# 加载配置
config = load_config()
IMAGE_DIR = config["image_dir"]
SLEEP_TIME = config["sleep_time"]
MULTI_CHOICE_SEQUENCES = config["multi_choice_sequences"]
CONFIDENCE = config["confidence"]
SCROLL_AMOUNT = config["scroll_amount"]
MAX_SCROLL_ATTEMPTS = config["max_scroll_attempts"]
SCROLL_WAIT_TIME = config["scroll_wait_time"]
NEXT_PAGE_WAIT = config["next_page_wait"]

# --------------------- 核心功能 ---------------------
def click_image(image_name, confidence=CONFIDENCE):
    """点击指定名称的图像"""
    image_path = f"{IMAGE_DIR}{image_name}.png"
    try:
        # 尝试在屏幕上定位指定的图像
        image_location = pyautogui.locateOnScreen(image_path, confidence=confidence)
        if image_location:
            # 点击图像所在位置
            pyautogui.click(image_location)
            return True
        return False
    except Exception as e:
        print(f"点击图像 {image_name} 失败: {str(e)}")
        return False

def smart_sleep(seconds=SLEEP_TIME):
    """智能等待"""
    time.sleep(seconds)

def detect_image(image_name, confidence=CONFIDENCE):
    """检测指定名称的图像是否存在"""
    image_path = f"{IMAGE_DIR}{image_name}.png"
    try:
        # 尝试在屏幕上定位指定的图像
        image_location = pyautogui.locateOnScreen(image_path, confidence=confidence)
        if image_location:
            print(f"检测到图像: {image_name}，位置: {image_location}")
            return True  # 返回检测结果
        return False
    except Exception as e:
        print(f"检测图像 {image_name} 失败: {str(e)}")
        return False

def handle_multi_choice():
    """处理多选题"""
    for sequence in MULTI_CHOICE_SEQUENCES:
        for option in sequence:
            smart_sleep()
            click_image(option)
        click_image("tj")
        if not click_image("hdcw"):  # 如果没有错误提示，说明答案正确
            return True
    return False

def handle_single_choice():
    """处理单选题"""
    # 尝试所有选项
    click_image("A")
    smart_sleep(1)
    click_image("tj")
    
    if click_image("hdcw"):  # 如果有错误提示
        for option in ['B', 'C', 'D']:
            if not click_image(option):
                break
            smart_sleep(1)
            click_image("tj")
            if not click_image("hdcw"):  # 如果没有错误提示，说明答案正确
                return True
    else:
        return True
    
    return False

def handle_task_completion():
    """处理任务点完成后的操作"""
    smart_sleep(0.6)
    
    # 检查是否还有未完成的任务点
    if  click_image("dxt") or click_image("A") or click_image("task"):
        return True
    
    # 检查是否已出现"下一页"按钮
    if click_image("next"):
        click_image("next")
        smart_sleep(NEXT_PAGE_WAIT)  # 等待新页面加载
        return True
    
    if click_image("next2"):
        click_image("next2")
        smart_sleep(NEXT_PAGE_WAIT)  # 等待新页面加载
        return True
    
    # 向下滚动直到检测到"下一页"或达到最大滚动次数
    scroll_attempts = 0
    while scroll_attempts < MAX_SCROLL_ATTEMPTS:
        # 滚动页面
        pyautogui.scroll(-400)
        smart_sleep(0.3)
        
        # 检查滚动后是否出现新任务点
        if click_image("dxt") or click_image("A") or click_image("task"):
            return True
        
        # 检查滚动后是否出现"下一页"按钮
        if click_image("next"):
            click_image("next")
            smart_sleep(NEXT_PAGE_WAIT)  # 等待新页面加载
            return True
        
        if click_image("next2"):
            click_image("next2")
            smart_sleep(NEXT_PAGE_WAIT)  # 等待新页面加载
            return True
        
        scroll_attempts += 1
    
    return False

# --------------------- 键盘监听 ---------------------
def setup_keyboard_listener():
    """设置键盘监听器"""
    print("程序已启动，按 ESC 键可随时停止程序...")
    keyboard.add_hotkey('esc', stop_program)

# 全局运行状态
running = True

def stop_program():
    """停止程序运行"""
    global running
    running = False
    print("\n正在停止程序，请稍候...")

# --------------------- 主程序 ---------------------
def main():
    global running
    
    print_usage_guide()  # 打印操作指南
    a=input("按1后程序将执行...")  # 等待用户确认
    if a=='1':
        # 最小化vscode
        pyautogui.click(2234, 0)
        print("程序启动，最小化vscode")
        smart_sleep(0.6)
        
        # 设置键盘监听
        setup_keyboard_listener()
        
        while running:
            if click_image("zjcs"):  # 到章末的章节检测时停止
                print("检测到章节测试，停止运行")
                break
            
            while click_image("task") and running:
                if  click_image("pause"): # 当检测到任务点，就去找pause按钮
                    while not detect_image("jieshu1"):
                        smart_sleep(10)
                        continue
                if not click_image("pause") : 
                    pyautogui.scroll(-250)  # 如果没找到pause按钮，就代表是页面不够下去

                if click_image("dxt") and running:  # 当识别到多选题的字眼时
                    handle_multi_choice()
                elif click_image("A") and running:  # 识别到视频中跳出有A选项的选择题
                    handle_single_choice()
                elif click_image("bf")  and running:  # 中途视频意外暂停时对播放按钮进行点击
                    while not detect_image("jieshu1"):
                        smart_sleep(10)
                        continue

            if running and detect_image("finish"):  # 识别到任务点已完成的图片
                handle_task_completion()
            
            elif running:
                    # 等待一段时间再继续检测
                    handle_task_completion()
                    smart_sleep(0.6)
        
        print("程序安全停止")

if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        print(f"程序发生异常: {str(e)}")
    finally:
        # 清理键盘监听
        keyboard.unhook_all()
        input("按Enter键退出...")